/**
 * 
 */
package com.da.landlord;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.da.finance.DaFinanceStatement;
import com.espirit.eap.sa.LoginUser;
import com.espirit.eap.sa.LoginUserService;
import com.espirit.eap.sa.Privilege;
import com.espirit.eap.sa.PrivilegeService;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.model.Reference;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.security.SafeManager;
import com.googlecode.cswish.struts.ContextHolder;
import com.googlecode.cswish.struts.ServletRedirectResult;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.ra.landlord.Building;
import com.ra.landlord.BuildingService;
import com.ra.landlord.LandlordAssistUser;
import com.ra.landlord.LandlordOwnerUser;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.util.SmsService;

/**
 * 权限管理: 1.房东对房东管理员的新增/修改/删除; 
 * 		  2.房东分配房源给管理员; 
 *        3.房东分配权限给管理员;
 * @author Jebel Qin
 * @date 2015年6月11日
 * @since v1.0
 */

@Service
public class AuthUserService 
{
	private static Logger logger = LoggerFactory.getLogger(AuthUserService.class);
	
	@Resource
	private GenericService genericService;
	
	@Resource
	private SmsService smsService;
	
	@Resource
	private LandlordUserService landlordUserService;
	
	@Resource
	private LoginUserService loginUserService;
	
	@Resource
	private BuildingService buildingService;
	
	@Resource
	private PrivilegeService privilegeService;
	
	@Resource
	private SafeManager safeManager;
	
	//只要操作权限管理模块，每次总是自动设置的权限: frame页面和欢迎页面
	private static final String[] ALWAYS_PRIVILEGE_MODEL_NAME = {"da.landlord.frame", "da.workbench.welcome", "ra.landlord.workLog",
		"ra.landlord.landlordUser","ra.landlord.building","da.landlord.daSuite","da.print.batchPrint",	"ra.util.addressCode","ra.landlord.room",	"ra.landlord.feeRuleCfg",
		"ra.landlord.fee","da.finance.daFinanceCategory"};
	private static final String[] ALWAYS_PRIVILEGE_METHOD = {"index", "index", "ALL", "getLandlordUser","searchBuilding",
		"easyRuleCfg","searchDaRoom","searchCode","searchWithRental","search","search","search"};
	
	private static List<String> ALWAYS_PRIVILEGE; 
	
	private static Map<Integer, AuthAction> authActionMap;
	
	public void authDataInit()
	{
		logger.info("AuthUserService.authDataInit begin...");
		
		//Delete exit records
		List<AuthRoot> oldAuthRoot = genericService.searchAll(new AuthRoot()).getData();
		if (oldAuthRoot != null && !oldAuthRoot.isEmpty())
		{
			for (AuthRoot oldroot : oldAuthRoot)
			{
				genericService.delete(oldroot);
			}
		}
		
		//Get all privilege configure.
		Map<String, Privilege> privMap = new HashMap<>();
		List<Privilege> allPrivs = genericService.searchAll(new Privilege()).getData();
		for (Privilege priv : allPrivs)
		{
			privMap.put(priv.getModelSimpleName() +"." + priv.getMethod(), priv);
		}

		initRootData(privMap, "房源管理", Arrays.asList(
				"da.landlord.room._search",
				"da.landlord.room.search",
				"ra.landlord.room.search",
				"da.landlord.roomSource._add", 
				"da.landlord.daSuite._update",
				"ra.landlord.feeRuleCfg.searchMeterFeeRule",
				"da.landlord.daSuite.searchRoom",
				"da.landlord.daSuite.search",
				"ra.landlord.room.searchRoomsInGraphic", 
				"ra.landlord.room._update",
				"ra.landlord.roomItemCfg.search", 
				"ra.landlord.room._search",
				"da.landlord.daRoom._updateBookAgreement",
				"ra.landlord.building.search", 
				"ra.landlord.building.print",
				"ra.landlord.building._update",             //TODO这个跟峰哥的不一致
				"da.landlord.roomSource._batchAdd",
				"ra.landlord.room.searchRoomsInList",
				"ra.landlord.buildingFloor.searchBuildingFloor",
				"da.landlord.roomSource.copyBuildingFloor", // TODO 将本层复制到另外的层数中，此链接的位置
				"ra.landlord.room.searchRoom "), 
				Arrays.asList("da.landlord.daSuite.addSuite", 
						"da.landlord.roomSource.add",
						"ra.landlord.room.deleteRoom",
						"da.landlord.daSuite.delete",
						"da.landlord.daSuite.add",
						"ra.landlord.room.update",
						"ra.landlord.room.updateRoom", 
						"da.landlord.daSuite.update",
						"ra.landlord.room.add", 
						"ra.landlord.room.delete",
						"ra.landlord.building.add",
						"ra.landlord.building.update",
						"ra.landlord.building.delete",
						"da.landlord.roomSource._updateRooms",
						"da.landlord.roomSource.batchAddRooms",
						"ra.landlord.building.updateBuilding",
						"da.landlord.roomSource.updateRooms",
						"ra.landlord.room.addRoom",
						"da.landlord.roomSource.deleteRooms",
						"da.landlord.roomSource.update"));

		
/*		initRootData(privMap, "楼栋管理", Arrays.asList(
				"ra.landlord.building.search", 
				"ra.landlord.building.print",
				"ra.landlord.building._update",             //TODO这个跟峰哥的不一致
				"da.landlord.roomSource._batchAdd",
				"ra.landlord.room.searchRoomsInList",
				"ra.landlord.buildingFloor.searchBuildingFloor",
				"da.landlord.roomSource.copyBuildingFloor", // TODO 将本层复制到另外的层数中，此链接的位置
				"ra.landlord.room.searchRoom "),
				Arrays.asList(
				"ra.landlord.building.add",
				"ra.landlord.building.update",
				"ra.landlord.building.delete",
				"da.landlord.roomSource._updateRooms",
				"da.landlord.roomSource.batchAddRooms",
				"ra.landlord.building.updateBuilding",
				"da.landlord.roomSource.updateRooms",
				"ra.landlord.room.addRoom",
				"da.landlord.roomSource.deleteRooms"));*/

		initRootData(privMap, "收租", Arrays.asList(
				"da.landlord.daRoom._collectRental",
				"ra.landlord.room._collectRental",
				"da.landlord.daChargeBill.search",
				"da.landlord.daChargeBill.print"), Arrays.asList(
				"da.landlord.daRoom.collectRental",
				"ra.landlord.room.collectRental",
				"da.landlord.daChargeItem.add",
				"da.landlord.daChargeItem.update",
				"da.landlord.daChargeBill.createChargeBill",
				"da.landlord.daConfirmMoney.confirmMoneyFromCollectForRa",
				"da.landlord.daConfirmMoney.confirmMoneyFromCollectForDa"));
		

		initRootData(privMap, "预定", Arrays.asList("da.landlord.daRoom._book",
				"ra.landlord.room._book"), Arrays.asList(
				"da.landlord.daRoom.book", 
				"ra.landlord.room.book"));

		initRootData(privMap, "收费记录", Arrays.asList(
				"ra.landlord.fee._searchRoomHasPaidFee"), 
				Arrays.asList(
				"ra.landlord.fee.deleteFee",
				"da.print.batchPrint.printOneDaFee",
				"ra.landlord.fee.add",
				"ra.landlord.fee.delete",
				"ra.landlord.fee.update",
				"ra.landlord.fee.print",
				"ra.landlord.fee.calculate"));

		initRootData(privMap, "出租",
				Arrays.asList("ra.landlord.room._rent",
				"da.landlord.daRoom._rent",
				"da.landlord.daRoom._updateAgreement",
				"ra.landlord.agreement._update",
				"ra.landlord.tenantUser.search",
				"da.landlord.daSuite._unRent",
				"da.landlord.daSuite._rentRoom",
				"ra.landlord.roomRent._update"), 
				Arrays.asList(
				"ra.landlord.room.rent",
				"da.landlord.daRoom.rent",
				"da.landlord.daRoom.updateAgreement",
				"ra.landlord.agreement.updateNew",
				"ra.landlord.agreement.add",
				"ra.landlord.agreement.update",
				"ra.landlord.tenantUser.update",
				"da.landlord.daSuite.rentRoom"));

		initRootData(privMap, "抄表", Arrays.asList(
				"da.landlord.daMeter.showMeterFeeRuleCfgForSuite",
				"da.landlord.daRoomMeterItem.searchMetersForSuite",
				"da.landlord.daMeter.analyse", 
				"ra.landlord.room.searchMeter",
				"ra.landlord.meter.searchMeterByRoom",
				"ra.landlord.meter.search",
				"da.landlord.daMeter.search",
				"ra.landlord.meter.allSearch",
				"ra.landlord.meter.searchMeterCategory",
				"ra.landlord.shareUnit.searchWithMeter",
				"ra.landlord.meter.searchMeterByFeeRule",
				"da.landlord.daMeter.showMeterFeeRuleCfg",
				"da.landlord.daMeter.getSuiteMeters",
				"da.landlord.daRoomMeterItem.searchSuiteWithMeter"), Arrays.asList(
				"da.landlord.daMeter.deleteMeter",
				"da.landlord.daMeter.addMeters",
				"ra.landlord.meter.add",
				"ra.landlord.meter.update", 
				"ra.landlord.meter.delete",
				"da.landlord.daMeter.delete",
				"da.landlord.daMeter.update",
				"da.landlord.daMeter.add",
				"ra.landlord.meter.addMetersNew",
				"ra.landlord.meter.deleteMeterNew"));
	
		initRootData(privMap, "退租", Arrays.asList("ra.landlord.room._unRent",
				"da.landlord.daRoom._unRent"), Arrays.asList(
				"ra.landlord.room.throwLease",
				"da.landlord.daRoom.unRent",
				"ra.landlord.room.undoThrowLease",
				"da.landlord.daSuite.unRent"));


		initRootData(privMap, "网上收租单", Arrays.asList(
				"da.landlord.daConfirmMoney.view",
				"da.landlord.daConfirmMoney.searchRooms",
				"da.landlord.daConfirmMoney.searchWithFee"), Arrays.asList(
				"da.landlord.daConfirmMoney.confirmMoneyForDa",
				"da.landlord.daConfirmMoney.confirmMoneyForRa"));

		initRootData(privMap, "业主合约", Arrays.asList(
				"da.landlord.daOwner.search", "da.landlord.daOwner._update",
				"da.landlord.daOwner._pay"), Arrays.asList(
						"da.landlord.daOwner.add",
				"da.landlord.daOwner.addDaOwner", "da.landlord.daOwner.delete",
				"da.landlord.daOwner.stopAgreement", "da.landlord.daOwner.pay"));

		initRootData(privMap, "批量打印", Arrays.asList("da.print.room._search",
				"da.print.batchPrint.searchRaRoom"),
				Arrays.asList("da.print.batchPrint.printRaFee","da.print.batchPrint.printDaFee"));

		initRootData(privMap, "品牌公寓",
				Arrays.asList("ra.brand.brandApartment.apply"),
				Arrays.asList("ra.brand.brandApartment.brandApartmentSubmit"));

		initRootData(privMap, "发布推广", Arrays.asList(
				"ra.wr.roomPublish._searchPublishRoom",
				"ra.wr.roomPublish.searchAllPublishRoomInfo",
				"ra.rent.roomInfo.search",
				"ra.rent.roomInfo._searchPublishRoom",
				"ra.wr.roomPublish.search"),
				Arrays.asList("ra.rent.roomInfo.updateSingleRoomPubInfo",
						"ra.rent.roomInfo.update"));
		
		initRootData(privMap, "短信催缴",
				Arrays.asList("ra.weixin.personality.feeNotification.add", 
						"ra.weixin.personality.reminderLetter.getMessageCountByLandlordUser",
						"ra.weixin.personality.reminderLetter.getSendUsers", "ra.landlord.building.getBuildRooms"), 
				Arrays.asList("ra.weixin.personality.reminderLetter.sendReminderLetterByRealTimeDaAndRa"));

		initRootData(privMap, "打印二维码",
				Arrays.asList("da.landlord.download.view"),
				Arrays.asList("da.landlord.download.downloadCodeImg"));

		initRootData(privMap, "收费项管理", Arrays.asList(
				"ra.landlord.feeRule.search",
				"ra.landlord.feeRuleCfgDesc.searchAllFeeDesc",
				"ra.landlord.feeRuleCfgDesc._update",
				"ra.landlord.feeRuleCfg.searchFeeRuleCfg",
				"ra.landlord.feeRuleCfgDesc.search",
				"da.landlord.daChargeItem.search",
				"da.andlord.daFeeRule.search",
				"ra.landlord.feeAddition.search",
				"ra.landlord.feeAdditionRecord.search"
				), Arrays.asList(
				"ra.landlord.feeAdditionRecord.update",
				"ra.landlord.feeRule.update",
				"ra.landlord.feeRuleCfgDesc.addDescAndFeeRuleCfg",
				"ra.landlord.feeRuleCfgDesc.updateDescAndSingleFeeRuleCfg",
				"da.andlord.daFeeRule.deleteFeeRuleDescCfg",
				"ra.landlord.feeRuleCfgDesc.add",
				"ra.landlord.feeRuleCfgDesc.update",
				"ra.landlord.feeRuleCfgDesc.delete",
				"ra.landlord.feeRuleCfg.add", 
				"ra.landlord.feeRuleCfg.delete",
				"da.andlord.daFeeRule.update",
				"da.landlord.daFeeRule.delete",
				"ra.landlord.feeAddition.update"));

		initRootData(privMap, "分摊管理", Arrays.asList(
				"ra.landlord.shareUnit.search",
				"ra.landlord.shareUnit.searchShareUnit",
				"ra.landlord.share_unit._update",
				"ra.landlord.share_unit.search"), Arrays.asList(
				"ra.landlord.shareUnit.addShareUnit",
				"ra.landlord.shareUnit.deleteShareUnit",
				"ra.landlord.shareUnit.add",
				"ra.landlord. shareUnit.update",
				"ra.landlord.shareUnit.delete",
				"ra.landlord.shareUnit.updateShareUnit",
				"ra.landlord.shareUnit.update"));

		initRootData(privMap, "财务管理", Arrays.asList(
				"da.finance.financeStatistics.analyse",
				"da.finance.financeStatistics.search",
				"da.finance.daFinanceStatement.search",
				"da.finance.daFinanceStatement._update",
				"da.finance.daFinanceStatement.getAllRoom",
				"da.finance.daFinanceStatement.getAllTransaction",
				"da.finance.daFinanceStatement.getAllTradeCategory",
				"da.landlord.daRoom.search",
				"ra.landlord.simpleRoom.search",
				"ra.landlord.feeRuleCfgDesc.get"), 
				Arrays.asList(
				"da.finance.daFinanceStatement.update",
				"da.finance.daFinanceStatement.add",
				"da.finance.daFinanceStatement.delete",
				"da.finance.daFinanceCategory.add",
				"da.finance.daFinanceCategory.update",
				"da.finance.daFinanceCategory.delete"));

/*		initRootData(privMap, "权限管理", Arrays.asList(
				"da.landlord.authUser.list", "da.landlord.authUser._update"),
				Arrays.asList("da.landlord.authUser.update",
						" da.landlord.authUser.delete",
						"da.landlord.authUser._assignBuilding",
						"da.landlord.authUser.assignBuilding",
						"da.landlord.authUser._assignAuth",
						"da.landlord.authUser.assignAuth"));*/

		initRootData(privMap, "密码安全",
				Arrays.asList("ra.landlord.landlordUser._resetPassword"),
				Arrays.asList("ra.landlord.landlordUser.resetPasswordAuth","ra.landlord.landlordUser.resetPwd"));

		initRootData(privMap, "工作日志",
				Arrays.asList("ra.landlord.workLog.search"), 
				Arrays.asList(
						"ra.landlord.workLog.addWorkLog",
						"ra.landlord.workLog.updateWorkLog",
						"ra.landlord.workLog.deleteWorkLog"));

		initRootData(privMap, "便民服务", Arrays.asList(
				"ra.weixin.o2o.serviceInfo.search",
				"ra.weixin.o2o.serviceType.search",
				"ra.weixin.o2o.serviceType.getAllServiceType",
				"ra.weixin.o2o.serviceInfo.getOptionalZones"), Arrays.asList(
				"ra.weixin.o2o.serviceInfo.addServiceInfo",
				"ra.weixin.o2o.serviceInfo.add",
				"ra.weixin.o2o.serviceInfo.update",
				"ra.weixin.o2o.serviceInfo.delete",
				"ra.weixin.o2o.serviceInfo.updateServiceInfo",
				"ra.weixin.o2o.serviceInfo.deleteServiceInfo"));

		logger.info("AuthUserService.authDataInit end...");
	}
	
	private AuthRoot initRootData( Map<String, Privilege> privMap, String rootName, List<String> views, List<String> updates)
	{
		AuthRoot root = new AuthRoot(rootName);
		AuthAction action1 = new AuthAction("浏览");
		AuthAction action2 = new AuthAction("编辑");
		List<AuthAction> acitons = new ArrayList<AuthAction>();
		acitons.add(action1);
		acitons.add(action2);
		root.setActions(acitons);
		action1.setRoot(root);
		action2.setRoot(root);
		
		List<Privilege> viewPrivis = new ArrayList<Privilege>();
		for (String privStr : views)
		{
			viewPrivis.add(privMap.get(privStr));
		}
		
		List<Privilege> updatePrivis = new ArrayList<Privilege>();
		for (String privStr : updates)
		{
			updatePrivis.add(privMap.get(privStr));
		}
		action1.setPrivileges(viewPrivis);
		action2.setPrivileges(updatePrivis);
		genericService.add(root);
		return root;
	}
	
	/**
	 * 查询房东管理员列表
	 * @return
	 */
	@Rest(type="search")
	public PageInfo<LandlordAssistUser> list(LandlordAssistUser model, int start, int limit,
    		String sort, String dir, boolean oldSearch, Reference<QLInfo> qlInfoRef) 
    {
		checkLoginAuthValidation();
		
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		if (landlordUser instanceof LandlordOwnerUser) 
		{
			model.setLandlordOwnerUser((LandlordOwnerUser) landlordUser);
			return genericService.search(model, start, limit, sort, dir, oldSearch, qlInfoRef);
		} 
		else 
		{
			return new PageInfo<LandlordAssistUser>();
		}
	}
	
	@Rest(type="search")
	public LandlordAssistUser _update(LandlordAssistUser model)
	{
		tmpNotReady();
		
		if (model.getId() != null)
		{
			genericService.view(model);
		}
		return model;
	}
	
	/**
	 * 新增/修改房东管理员
	 * @param model
	 */
	@Rest(type="update")
	@Transactional
	public Result update(LandlordAssistUser model, String verifyCode)
	{
		tmpNotReady();
		
		checkLoginAuthValidation();
		if (model.getId() == null)
		{
			if (StringUtils.isEmpty(verifyCode))
			{
				throw new ApplicationException("验证码不能为空！");
			}
			LandlordUser landlordUser = landlordUserService.getLoginUser();
			model.setLandlordOwnerUser((LandlordOwnerUser)landlordUser);
			LandlordUser dbLandlordAssistUser = landlordUserService.addLandlordUser(model, verifyCode, true);  //TODO falst -> true
			
			initLandlordAssistUserPrevelliges(dbLandlordAssistUser.getId());
		}
		else
		{
			LandlordAssistUser dbLandlord = genericService.load(LandlordAssistUser.class, model.getId());
			checkAuthValidation(dbLandlord);
			
			model.setPhone(dbLandlord.getPhone());
			landlordUserService.update(model, null);
		}
		
		Result result = new ServletRedirectResult("/da/landlord/authUser.list.html");
		ObjectFactory.getInstance().autoWireBean(result);
		return result;
	}
	
	/**
	 * 新增/修改房东管理员
	 * @param model
	 */
	@Rest(type="update")
	public Result changeUserRole(LandlordUser model, String verifyCode)
	{
		checkLoginAuthValidation();
		
		String existedVerifyCode = smsService.getVerifyCode(model.getPhone());
		boolean pass = StringUtils.isNotEmpty(existedVerifyCode) && existedVerifyCode.equals(verifyCode);
		if (!pass) {
			LoginUser loginUser = loginUserService.getLoginUser();
			if (loginUser == null || !loginUser.isSuperAdmin()) {				
				smsService.reduceTryCount(model.getPhone());
				throw new ApplicationException("手机校验码不正确");
			}
		}
		
		LandlordUser example = new LandlordUser();
		example.setPhone(model.getPhone());
		LandlordUser dbModel = genericService.searchAll(example).getData(0);
		if (isOwnRoomSource(dbModel))
		{
			logger.warn("Own Rooms: Can not change landlord owner to landlord assist by phone:" + model.getPhone());
			throw new ApplicationException("该房东名下还有房源，不能转为管理员！");
		}
		
		if (isOwnLandlordAssist(dbModel))
		{
			logger.warn("Own Assistants: Can not change landlord owner to landlord assist by phone:" + model.getPhone());
			throw new ApplicationException("该房东有管理员，不能转为管理员！");
		}
		
		if (dbModel instanceof LandlordAssistUser)
		{
			logger.warn("Assistants: Can not change landlord owner to landlord assist by phone:" + model.getPhone());
			throw new ApplicationException("该账号已经是管理员！");
		}
		
		//删除原来的财务记录
		if (dbModel instanceof LandlordOwnerUser)
		{
			DaFinanceStatement financeStat = new DaFinanceStatement();
			financeStat.setLandlordUser((LandlordOwnerUser)dbModel);
			List<DaFinanceStatement> financeList = genericService.searchAll(financeStat).getData();
			for (DaFinanceStatement daFinanceStatement : financeList)
			{
				logger.info("changeUserRole: Delete daFinanceStatement with landlorduserId:" + dbModel.getId() + " and daFinanceStatementId:" + daFinanceStatement.getId());
				genericService.delete(daFinanceStatement, true);
			}
		}
		
		// 1. update model property
		model.setId(dbModel.getId());
		if (StringUtils.isNotEmpty(model.getPassword())) {
			String encryptPassword = loginUserService.getEncryptPassword(model.getPassword());
			String vcPassword = landlordUserService.convertJavaPasswordToVcPassword(encryptPassword);
			model.setPassword(vcPassword);
			
			// update the login user password
			LoginUser loginUser = dbModel.getLoginUser();
			if (loginUser != null) {
				loginUser.setPassword(encryptPassword);
				genericService.merge(loginUser);
			}
		}
		genericService.update(model, true, null, null);
		
		// 2. change the model type
		LandlordAssistUser assistUser = genericService.changeModelType(dbModel, LandlordAssistUser.class);
		
		// 3. change the relationship between login user and the assist user
		LandlordUser loginUser = landlordUserService.getLoginUser();
		LandlordUser dbLoginUser = genericService.load(loginUser);
		assistUser.setLandlordOwnerUser((LandlordOwnerUser) dbLoginUser);
		genericService.merge(assistUser);
		
		//重要:初始化管理员的权限, 要不然就会有房东的权限
		initLandlordAssistUserPrevelliges(assistUser.getId());
		
		//转换成功, 删除验证码
		smsService.removeVerifyCode(model.getPhone());
		
		Result result = new ServletRedirectResult("/da/landlord/authUser.list.html");
		ObjectFactory.getInstance().autoWireBean(result);
		return result;
	}
	
	/**
	 * 新增房东管理员初始化权限: 没有任何权限
	 * @param landlordAssistId
	 */
	private void initLandlordAssistUserPrevelliges(Integer landlordAssistId)
	{
		LandlordAssistUser dbLandlordAssistUser = genericService.load(LandlordAssistUser.class, landlordAssistId);
		LoginUser loginAssistUser = dbLandlordAssistUser.getLoginUser();
		setAlwaysPrivilege();
		privilegeService.update(loginAssistUser, false, ALWAYS_PRIVILEGE);
	}
	
	/**
	 * 删除房东管理员
	 * @param ids
	 */
	@Rest(type="delete")
	@Transactional
	public Result delete(List<LandlordAssistUser> model)
	{
		checkLoginAuthValidation();
		
		//TODO 检查是否分配了楼房?
		for (LandlordAssistUser auth : model)
		{
			//genericService.delete(auth);
			LandlordAssistUser dbAssistUser = genericService.load(auth);
			checkAuthValidation(dbAssistUser);
			
			//删除所有已经分配的房源
			removeBuildingAssigned(dbAssistUser);
			
			landlordUserService.delete(dbAssistUser);
		}
		
		Result result = new ServletRedirectResult("/da/landlord/authUser.list.html");
		ObjectFactory.getInstance().autoWireBean(result);
		return result;
	}
	
	@Rest(type="update")
	@Transactional
	public List<BuildingVo> _assignBuilding(Integer landlordAssistId)
	{
		tmpNotReady();
		
		List<BuildingVo> result = new ArrayList<BuildingVo>();
		//
		LandlordAssistUser landlordAssistUser = genericService.load(LandlordAssistUser.class, landlordAssistId);
		checkAuthValidation(landlordAssistUser);
		
		genericService.refresh(landlordAssistUser);
		
		List<Building> assignedBuildings = landlordAssistUser.getBuildings();
		System.out.println("Assigned building size: " + assignedBuildings.size());

		List<Building> buildingList = buildingService.searchBuilding();
		for (Building building : buildingList)
		{
			BuildingVo v = new BuildingVo(building.getId(), building.getName(), building.getDetailAddress(), building.getRooms().size());
			v.setBuildingFlag(true);
			if (assignedBuildings.contains(building))
			{
				v.setStatus(BuildingVo.STATUS_SELECTED);
			}
			result.add(v);
		}
		
		//Suites
		LandlordOwnerUser landlordOwnerUser = genericService.load(landlordUserService.getLoginUser().getOwnerUser());
		DaSuite suite = new DaSuite();
		suite.setLandlordUser(landlordOwnerUser);
		List<DaSuite> suiteList = genericService.searchByModel(suite, Condition.DEFAULT).getData();
		//List<DaSuite> suiteList = genericService.searchAll(suite).getData();  No permition
		
		List<LandlordUser> assists = new ArrayList<LandlordUser>();
		assists.add(landlordAssistUser);
		//suite.setLandlordUsers(landlordUsers);
		suite.setLandlordUsers(assists);
		List<DaSuite> dbSuiteList = genericService.searchAll(suite).getData();
		System.out.println("Assigned suite size: " + dbSuiteList.size());
		
		String addressStr = "";
		for (DaSuite su : suiteList)
		{
			if (su.getAddress() != null)
			{
				addressStr = su.getAddress().getFullName();
			}
			BuildingVo v = new BuildingVo(su.getId(), su.getName(), addressStr, su.getRooms().size());
			v.setBuildingFlag(false);
			if (dbSuiteList.contains(su))
			{
				v.setStatus(BuildingVo.STATUS_SELECTED);
			}
			result.add(v);
		}
		return result;
	}
	
	/**
	 * 分配房源: 包括楼房和套间
	 * @param model
	 * @param suite
	 * @param landlordAssistId
	 * @return
	 */
	@Rest(type="update")
	@Transactional
	public boolean assignBuilding(List<Building> model, List<DaSuite> suite, Integer landlordAssistId)
	{
		tmpNotReady();
		
		checkLoginAuthValidation();
		
		LandlordAssistUser dbLandlordAssistUser = genericService.load(LandlordAssistUser.class, landlordAssistId);
		checkAuthValidation(dbLandlordAssistUser);
		
		//删除所有已经分配的房源
		removeBuildingAssigned(dbLandlordAssistUser);

		//Add new assigned buildings.
		for (Building building : model) 
		{
			Building dbBuilding = genericService.load(building, false);
			dbBuilding.getLandlordUsers().add(dbLandlordAssistUser);
			genericService.merge(dbBuilding);
			//genericService.update(dbBuilding, false, Arrays.asList("landlordUsers"), null);   //effective as merge method
		}

		//Add new assigned suites.
		for (DaSuite su : suite)
		{
			//DaSuite dbSuite = genericService.searchAll(su).getData().get(0);
			DaSuite dbSuite = genericService.load(su, false);
			dbSuite.getLandlordUsers().add(dbLandlordAssistUser);
			genericService.merge(dbSuite);
		}
		return true;
	}
	
	/**
	 * 删除房东管理员时删除其已经分配的房源
	 */
	private void removeBuildingAssigned(LandlordAssistUser dbLandlordAssistUser)
	{
		//Remove all buildings assigned.
		List<Building> dbBuildings = dbLandlordAssistUser.getBuildings();
		System.out.println("dbBuildings size: " + dbBuildings.size());
		for (Building dbbuilding : dbBuildings)
		{
			dbbuilding.getLandlordUsers().remove(dbLandlordAssistUser);
			genericService.merge(dbbuilding);
			//genericService.update(dbbuilding, false, Arrays.asList("landlordUsers"), null);   //effective as merge method
		}
		
		//Remove all suites assigned.
		DaSuite searchSuiteModel = new DaSuite();
		List<LandlordUser> assists = new ArrayList<LandlordUser>();
		assists.add(dbLandlordAssistUser);
		searchSuiteModel.setLandlordUsers(assists);
		
		List<DaSuite> dbSuiteList = genericService.searchByModel(searchSuiteModel, Condition.DEFAULT).getData();
		System.out.println("dbSuiteList size: " + dbSuiteList.size());
		for (DaSuite daSuite : dbSuiteList)
		{
			daSuite.getLandlordUsers().remove(dbLandlordAssistUser);
			genericService.merge(daSuite);
		}
	}
	
	/**
	 * 手动权限检查: 分配房东管理员权限时，登录用户必须是房东管理员所属的房东
	 * @param dbLandlordAssistUser
	 */
	private void checkAuthValidation(LandlordAssistUser dbLandlordAssistUser)
	{
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		if (!dbLandlordAssistUser.getOwnerUser().getId().equals(landlordUser.getId())) 
		{
			throw new ApplicationException("非法数据", dbLandlordAssistUser.getId());
		}
	}
	
	/**
	 * 手动权限检查: 房东管理员不能操作权限管理模块
	 */
	private void checkLoginAuthValidation()
	{
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		if (landlordUser instanceof LandlordAssistUser) 
		{
			throw new ApplicationException("非法数据", landlordUser.getId());
		}
	}
	
	@Rest(type="update")
	public List<AuthRoot> _assignAuth(Integer landlordAssistId)
	{
		tmpNotReady();
		
		LandlordAssistUser dbLandlordAssistUser = genericService.load(LandlordAssistUser.class, landlordAssistId);
		landlordUserService.fixNoLoginUser(dbLandlordAssistUser);   //处理PC端数据问题: loginUser为空时，创建loginUser对象并关联 LandlordAssistUser
		
		LoginUser loginAssistUser = dbLandlordAssistUser.getLoginUser();
		List<Privilege> hasPrivileges =  loginAssistUser.getPagePermissions();

		List<AuthRoot> list = genericService.searchAll(new AuthRoot()).getData();
		for (AuthRoot authRoot : list)
		{
			boolean rootChecked = true;
			List<AuthAction> actions = authRoot.getActions();
			for (AuthAction authAction : actions)
			{
				List<Privilege> privList = authAction.getPrivileges();
				for (Privilege privilege : privList)
				{
					if (hasPrivileges.contains(privilege))
					{
						authAction.setChecked(true);
						break;
					}
				}
				if (authAction.getChecked() == null || !authAction.getChecked())
				{
					rootChecked = false;
				}
			}
			authRoot.setChecked(rootChecked);
		}
		
		return list;
	}
	
	/**
	 * 分配权限
	 * @param actionId
	 * @param landlordAssistId
	 * @return
	 */
	@Rest(type="update")
	@Transactional
	public boolean assignAuth(Integer[] actionId,  Integer landlordAssistId)
	{
		tmpNotReady();
		
		checkLoginAuthValidation();
		LandlordAssistUser dbLandlordAssistUser = genericService.load(LandlordAssistUser.class, landlordAssistId);
		checkAuthValidation(dbLandlordAssistUser);
		
		setAlwaysPrivilege();
		
		List<String> privileges = new ArrayList<String>();
		if (ALWAYS_PRIVILEGE != null)
		{
			privileges.addAll(ALWAYS_PRIVILEGE);
		}
		
		if (actionId.length > 0)    
		{
			initialCacheActionMap();

			for (Integer actId : actionId)
			{
				AuthAction authAct = authActionMap.get(actId);
				if (authAct != null)
				{
					privileges.addAll(authAct.getPrivilegeIds());
				}
			}
		}
		
		LoginUser loginUser = dbLandlordAssistUser.getLoginUser();
		//loginUserService.updateUserPrivilege(loginUser, false, privileges);
		privilegeService.update(loginUser, false, privileges);
		
		//权限修改即时生效
		safeManager.updatePermission(ServletActionContext.getRequest(), loginUser.getId().toString(), ContextHolder.get().getSiteName());

		return true;
	}
	
	/**
	 * 缓存AuthAction
	 */
	private void initialCacheActionMap()
	{
		if (authActionMap ==  null)
		{
			synchronized (this)
			{
				if (authActionMap == null)
				{
					authActionMap = new HashMap<Integer, AuthAction>();
					List<AuthRoot> authRoots = genericService.searchAll(new AuthRoot()).getData();
					for (AuthRoot authRoot : authRoots)
					{
						for (AuthAction authAction : authRoot.getActions())
						{
							logger.debug("###authAction.getPrivileges().size:" + authAction.getPrivileges().size());
							authActionMap.put(authAction.getId(), authAction);
						}
					}
				}
			}
		}
	}
	
	/**
	 * 设置默认权限
	 */
	private void setAlwaysPrivilege()
	{
			synchronized (this) 
			{
				if (ALWAYS_PRIVILEGE == null)
				{
					ALWAYS_PRIVILEGE = new ArrayList<String>(5);
					for (int i = 0; i < ALWAYS_PRIVILEGE_MODEL_NAME.length; i++)
					{
						Privilege privilege = new Privilege();
						privilege.setModelSimpleName(ALWAYS_PRIVILEGE_MODEL_NAME[i]);
						privilege.setMethod(ALWAYS_PRIVILEGE_METHOD[i]);
						Privilege dbPrivilege = (Privilege)genericService.searchAll(privilege).getData(0);
						if (dbPrivilege == null)
						{
							logger.warn("Privilege: <da.landlord.frame.index> is not be setting.");
						}
						else
						{
							ALWAYS_PRIVILEGE.add(String.valueOf(dbPrivilege.getId()));
						}
					}
				}
			}
	}
	
	@Rest(simpleServiceName="loginUser",type="free")
	public int checkPhoneIsNotExists(String phone,boolean checked){
		//1 通过 -手机号不存在   0不通过-手机号已存在 -1不通过-手机号是自己 -2该账号还有未删除房源，请先删除
		int passed = 1;
		if(checked)
		{
			passed = 1;
		}
		else if(landlordUserService.getLoginUser().getPhone().equals(phone))
		{
			passed = -1;
		}
		else
		{
			LandlordUser landlordUser=new LandlordUser();
			landlordUser.setPhone(phone);
			List<LandlordUser> list=genericService.searchAll(landlordUser).getData();
			if(list.size() > 0)
			{
				LandlordUser landlordOwnerUser = list.get(0);
				passed = 0;
				if (isOwnRoomSource(landlordOwnerUser))
				{
					passed = -2;
				}
				else if (isOwnLandlordAssist(landlordOwnerUser))
				{
					passed = -3;
				}
				else if (landlordOwnerUser instanceof LandlordAssistUser)
				{
					passed = -4;
				}
			}
		}
		return passed;
	}
	
	/**
	 * 检查房东下是否有房源
	 * @param landlordUser
	 * @return
	 */
	private boolean isOwnRoomSource(LandlordUser landlordUser)
	{
		boolean ownRoom = false;
		QLInfo qlInfo = new QLInfo("select count(a) from DaSuite a where a.landlordUser.id=" + landlordUser.getId(), true);
		int ownDaSuite = genericService.getCount(qlInfo, false);
		if (ownDaSuite > 0)
		{
			ownRoom = true;
		}
		
		if (!ownRoom)
		{
			QLInfo searchBuildingQl = new QLInfo("select count(b) from Building b where b.landlordUser.id = " + landlordUser.getId(), true);
			int ownBuildingCount = genericService.getCount(searchBuildingQl, false);
			if (ownBuildingCount > 0)
			{
				ownRoom = true;
			}
		}
		
		return ownRoom;
	}
	
	private boolean isOwnLandlordAssist(LandlordUser landlordUser)
	{
		boolean ownAssist = false;
		
		if (landlordUser instanceof LandlordOwnerUser)
		{
			LandlordAssistUser assist = new LandlordAssistUser();
			assist.setLandlordOwnerUser((LandlordOwnerUser)landlordUser);
			
			QLInfo searchBuildingQl = new QLInfo("select count(a) from LandlordAssistUser a where a.landlordOwnerUser.id = " + landlordUser.getId(), true);
			int ownAssistcount = genericService.getCount(searchBuildingQl, false);
			if (ownAssistcount > 0)
			{
				ownAssist = true;
			}
		}
		
		return ownAssist;
	}
	
	private void tmpNotReady()
	{
		//throw new ApplicationException("此功能暂时关闭！");  //TODO delete
	}
}
